/**
 * 
 */
package kr.co.insoft.driver.rackspace.process;

import java.io.Closeable;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import kr.co.insoft.driver.exception.DriverException;
import kr.co.insoft.driver.exception.ExceptionCode;
import kr.co.insoft.driver.rackspace.model.RackSpaceCredentialModel;
import kr.co.insoft.driver.rackspace.model.RackSpaceInstanceModel;

import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.google.common.collect.ImmutableSet;
import com.google.common.io.Closeables;
import com.google.inject.Module;

/**
 * 서버의 상세 정보를 반환한다.
 * 
 * @author IN-SOFT Inc. GoodwillDD(sylee@in-soft.co.kr)
 * 
 */
public class DetailServerProcess implements Closeable {

	private static final Logger logger = LoggerFactory
			.getLogger(DetailServerProcess.class);
	private final RackSpaceCredentialModel credentialModel;
	private final ComputeService computeService;

	public DetailServerProcess(RackSpaceCredentialModel credentialModel)
			throws DriverException {
		this.credentialModel = credentialModel;

		try {
			Assert.notNull(this.credentialModel);
			Assert.notNull(this.credentialModel.getUsername());
			Assert.notNull(this.credentialModel.getAccessKey());
		} catch (IllegalArgumentException e) {
			if (logger.isDebugEnabled()) {
				logger.debug("credentialModel : {}", this.credentialModel);
			}
			throw new DriverException(ExceptionCode.ARGUMENT_ERROR, e);
		}

		try {
			Iterable<Module> modules = ImmutableSet
					.<Module> of(new SLF4JLoggingModule());

			ComputeServiceContext context = ContextBuilder
					.newBuilder(this.credentialModel.getProvider())
					.credentials(this.credentialModel.getUsername(),
							this.credentialModel.getAccessKey())
					.modules(modules).buildApi(ComputeServiceContext.class);
			computeService = context.getComputeService();
		} catch (Exception e) {
			throw new DriverException(ExceptionCode.DRIVER_ERROR, e);
		}
	}

	public Set<RackSpaceInstanceModel> getServers() throws DriverException {
		Set<String> ids = new HashSet<String>();
		for (ComputeMetadata computeMetadata : computeService.listNodes()) {
			ids.add(computeMetadata.getId());
		}
		return getServers(ids);
	}

	public Set<RackSpaceInstanceModel> getServers(String... ids)
			throws DriverException {
		return getServers(Arrays.asList(ids));
	}

	public Set<RackSpaceInstanceModel> getServers(Collection<String> ids)
			throws DriverException {
		Set<RackSpaceInstanceModel> result = new HashSet<RackSpaceInstanceModel>();
		for (NodeMetadata nodeMetadata : computeService.listNodesByIds(ids)) {
			result.add(new RackSpaceInstanceModel(nodeMetadata));
		}
		return result;
	}

	public RackSpaceInstanceModel getServer(String id) throws DriverException {
		try {
			return new RackSpaceInstanceModel(
					computeService.getNodeMetadata(id));
		} catch (Exception e) {
			throw new DriverException(ExceptionCode.DRIVER_ERROR, e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.io.Closeable#close()
	 */
	@Override
	public void close() throws IOException {
		Closeables.close(computeService.getContext(), true);
	}

}
